S3初心者向け『例 4: バケット所有者が自分が所有しないオブジェクトへのクロスアカウントアクセス許可を付与』をやってみた
概要
大阪オフィスのちゃだいんです。
手を動かして学ぶために、公式ドキュメントのチュートリアルをやってみました。
Amazon S3のアクセス管理チュートリアル 最終回です。前回の続編で、内容は以下のものです。
例 4: バケット所有者が自分が所有しないオブジェクトへのクロスアカウントアクセス許可を付与 - Amazon Simple Storage Service
今回のシナリオでは、「アカウントAのバケットに、アカウントBのオブジェクトをアップロードして、そのオブジェクトへアカウントCのアクセスを許可する」という、アカウントが3つ登場するものです。
前提条件
AWS CLIが使用できる環境で行ってます。
また、2つのアカウントはドキュメントと同様に以下のように記載します。
AWSアカウントID | アカウントの呼び方 | アカウントの管理者ユーザー |
---|---|---|
1111-1111-1111 | アカウント A | AccountAadmin |
2222-2222-2222 | アカウント B | AccountBadmin |
3333-3333-3333 | アカウント C | AccountCadmin |
早速やってみた
1.(アカウントA作業)S3バケットを作成し、バケットポリシーを設定する
- アカウントAにて、S3バケット
190910testbucket
を作成します。 -
バケットポリシーはドキュメントのものを少し変更しています。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "111", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::222222222222:user/TestAdminB" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::190910testbucket/*" }, { "Sid": "112", "Effect": "Deny", "Principal": { "AWS": "arn:aws:iam::222222222222:user/TestAdminB" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::190910testbucket/*", "Condition": { "StringNotEquals": { "s3:x-amz-grant-full-control": "id=********************************************" } } } ] }
※ id=*******...の部分はダミーですが、実際はアカウントAの正規ユーザーIDをS3バケットから取得しています。
- コンソールで見るとこんな感じです。
2.(アカウントA作業)IAMポリシーを作成し、IAMロールに割り当てる
- アカウントCに使ってもらうためのIAMロールを、アカウントAにて作成します。
-
IAMロールに割り当てるIAMポリシーをまず作成します。
-
ドキュメントのポリシーのバケット名のみ以下変更してます。
- ポリシーの名前は
TestPolicyForC
として保存します。
- 次に、IAMロールを作成します。
-
ドキュメントから少しマネコンが変更になっていますが、Trusted entityのタイプは
Another AWS account
を選びます。
※ AccountIDでは、アカウントCのIDを入れています。
- 次に、先ほど作成した
TestPolicyForC
のポリシーをアタッチします。
- IAMロールの名前を
TestRoleForC
とし、Trusted entities がアカウントCになっていることを確認して、作成します。
- IAMロールはできました。これでアカウントA側の作業は終了です。
3.(アカウントB作業)オブジェクトをバケットにアップロードする
- 次はアカウントBの作業です。バケットポリシーにてアカウントBによるオペレーションが許可されているので、オブジェクトを実際にアップロードします。
$ aws s3api put-object --bucket 190910testbucket \ --key CheapGoodCurry.jpg --body ~/desktop/CheapGoodCurry.jpg \ --grant-full-control id="*************************************************************" \ --profile TestAdminB
※ id=*******...の部分はダミーですが、実際はアカウントAの正規ユーザーIDをS3バケットから取得しています。
- どうやらアップロードできたようです。
【コラム】今回のバケットポリシーの特徴
ちなみに少し遡りますが、今回のバケットポリシーは少し厳格なルールにしてあります。というのも、後半にDenyのポリシーを入れているためです。
ものすごくカジュアルに今回のバケットポリシーをいうと、
「222222222222
アカウントのTestAdminB
は、190910testbucket
に対して、s3:PutObject
してもOKよ。ただし、その時にバケット所有者である私(アカウントA)にそのオブジェクトに対してのフルコントロールの権限も同時にくれないとNGよ。」
というものです。
バケットポリシーのAllow
が前半、Deny
が後半となります。
この後半を入れた理由はなぜでしょうか?
理由は、これを入れておかないと、アカウントBから画像のアップロードができても、アカウントAやアカウントCが何もできない為です。
なので、バケットポリシーにて「オブジェクトに対するフルコントロール権を同時に与えてくれないオブジェクトのアップロード」は拒否するようにしている訳です。なるほど。
4.(アカウントC作業)IAMユーザーを作成し、ポリシーを割り当てる
- それではアカウントCの作業に入ります。
-
いつも通り、まずなんの権限も持たないIAMユーザー
TestUserC
を作成します。
- それからインラインポリシーにて、ドキュメントのポリシーを少し変更した以下を登録します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["sts:AssumeRole"], "Resource": "arn:aws:iam::111111111111:role/TestRoleForC" } ] }
5.(アカウントC作業)一時的な認証情報を発行する
- まず、先ほど作成した
TestUserC
のCredencialsを記入しておきます。
[profile TestUserC] aws_access_key_id = TestUserCAccessKeyID aws_secret_access_key = TestUserCSecretAccessKey
- 次に、
AWS CLI assume-role
コマンドを実行して、一時的な認証情報を発行します。
$ aws sts assume-role --role-arn arn:aws:iam::111111111111:role/TestRoleForC \ --profile TestUserC --role-session-name test { "AssumedRoleUser": { "AssumedRoleId": "AROA2UJCVL7Q46H472X7R:test", "Arn": "arn:aws:sts::111111111111:assumed-role/TestRoleForC/test" }, "Credentials": { "SecretAccessKey": "***********************************", "SessionToken": "************************************************************************************************************************************************************************************************************************************************************************", "Expiration": "2019-09-10T11:30:04Z", "AccessKeyId": "************************" } }
※ ******の箇所は全てダミーです。実際は文字列が入っています。
- 上記の通り、一時的な認証情報が発行されました。こちらをcredentialsに記入します。
[profile TempCred] aws_access_key_id = temp-access-key-ID aws_secret_access_key = temp-secret-access-key aws_session_token = session-token
6.(アカウントC作業)オブジェクトを取得する
- これがラストです。アカウントAのバケットに保存されたアカウントBの画像を、アカウントCが取得します。
-
ドキュメントのコマンドを修正し以下の通りに実行してみました。
$ aws s3api get-object --bucket 190910testbucket --key CheapGoodCurry.jpg SaveFileAs.jpg --profile TestTempCred { "AcceptRanges": "bytes", "ContentType": "binary/octet-stream", "LastModified": "Tue, 10 Sep 2019 10:15:02 GMT", "ContentLength": 1436514, "ETag": "\"a45be69192b1e5aaad0a4d18ed8ed14b\"", "Metadata": {} }
- いけました。ちなみに許可されていないアクションもやってみます。
$ aws s3api get-object-acl --bucket 190910testbucket --key CheapGoodCurry.jpg --profile TestTempCred An error occurred (AccessDenied) when calling the GetObjectAcl operation: Access Denied
- それは許さんと言われました。以上で終了です。
-
ちなみに
CheapGoodCurry.jpg
とは、以下の画像でした。(肥後橋の某人気立ち飲み屋さんが、昼間にランチでやっている安くて美味しいカレーです)
ハマったところ
ちなみにハマったポイントとして、
バケットポリシーの
"s3:x-amz-grant-full-control": "id=********************************************"
部分を作成する際に、コピペを誤って
"s3:x-amz-grant-full-control": "********************************************"
(id=がない)
という状態にしていた為、アカウントBから画像がアップロードできない問題に悩まされました。
ケアレスミスすぎる...
感想
とはいえ、アカウント3つ巴の運用で、さらにIAMロールによって別アカウントからのオペレーションを許可する方法がわかりました。途中でちらっと説明した今回のバケットポリシーのDenyの設定も、実運用の場では必須と言えそうです。
これにてS3公式ドキュメントのアクセス管理4つのチュートリアルを終えました。 おかげさまで、すこーしS3のアクセスポリシーのことが理解できた気がします。
しかし、まだまだ先は長い、深い。言葉にならないくらい。ですので、精進します。
誰かのお役に立てば幸いです。それではまた、大阪オフィスのちゃだいんでした。